<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\WorkDepartment\Logic;

use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Logger\LoggerFactory;
use MoChat\App\Corp\Contract\CorpContract;
use MoChat\App\Corp\Utils\WeWorkFactory;
use MoChat\App\WorkDepartment\Contract\WorkDepartmentContract;
use MoChat\App\WorkDepartment\Queue\SyncDepartmentQueue;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeDepartmentContract;

/**
 * Class SyncDepartmentListLogic.
 */
class SyncDepartmentListLogic
{
    /**
     * @Inject
     * @var WorkDepartmentContract
     */
    protected $workDepartmentService;

    /**
     * @Inject
     * @var CorpContract
     */
    protected $corpService;

    /**
     * @var StdoutLoggerInterface
     */
    protected $logger;

    /**
     * @Inject
     * @var WeWorkFactory
     */
    protected $weWorkFactory;

    /**
     * @Inject
     * @var SyncDepartmentQueue
     */
    protected $syncDepartmentQueue;

    /**
     * @Inject
     * @var WorkEmployeeContract
     */
    protected $workEmployeeService;

    /**
     * @Inject
     * @var WorkEmployeeDepartmentContract
     */
    protected $workEmployeeDepartmentService;

    public function handle(int $corpId, int $wxDepartmentId)
    {
        $loggerFactory = make(LoggerFactory::class);
        $this->logger = $loggerFactory->get(__CLASS__);
        $this->logger->debug(sprintf('同步子部门列表逻辑开始, 企业ID:%s, 部门ID:%s', (string) $corpId, (string) $wxDepartmentId));

        $this->getSubDepartmentIdList($corpId, $wxDepartmentId);
    }

    /**
     * 获取子部门id列表.
     */
    private function getSubDepartmentIdList(int $corpId, int $wxDepartmentId)
    {
        $wxDepartmentId = $wxDepartmentId > 0 ? $wxDepartmentId : null;
        $weWorkApp = $this->weWorkFactory->getUserApp($corpId, true);
        if (is_null($wxDepartmentId)) {
            $wxResult = $weWorkApp->department->simpleList();
        } else {
            $wxResult = $weWorkApp->department->simpleList($wxDepartmentId);
        }

        if ($wxResult['errcode'] !== 0) {
            $this->logger->error(sprintf('获取子部门ID列表出错，企业ID:%s，部门ID:%s，错误信息：%s', (string) $corpId, (string) $wxDepartmentId, $wxResult['errmsg']));
            return;
        }

        $wxDepartmentIdListResult = $wxResult['department_id'];
        $remoteDepartmentIdList = array_column($wxDepartmentIdListResult, 'id');
        $deleteDepartmentIdList = $this->diffDepartmentIdList($corpId, $remoteDepartmentIdList);

        $this->syncDeleteDepartment($corpId, $deleteDepartmentIdList);
        $this->syncDepartmentDetail($corpId, $wxDepartmentIdListResult);
    }

    /**
     * 比较是否有删除的部门.
     */
    private function diffDepartmentIdList(int $corpId, array $remoteDepartmentIdList): array
    {
        $localDepartmentList = $this->workDepartmentService->getWorkDepartmentsByCorpId($corpId, ['id', 'wx_department_id']);
        $localDepartmentIdList = array_column($localDepartmentList, 'wx_department_id');
        $deleteDepartmentIdList = [];
        $deleteWxDepartmentIdList = array_diff($localDepartmentIdList, $remoteDepartmentIdList);
        if (! empty($deleteWxDepartmentIdList)) {
            foreach ($localDepartmentList as $localDepartment) {
                if (in_array($localDepartment['wxDepartmentId'], $deleteWxDepartmentIdList)) {
                    $deleteDepartmentIdList[] = $localDepartment['id'];
                }
            }
        }

        return $deleteDepartmentIdList;
    }

    /**
     * 删除在远程微信服务端已删除的部门.
     */
    private function syncDeleteDepartment(int $corpId, array $deleteDepartmentIdList)
    {
        if (empty($deleteDepartmentIdList)) {
            return;
        }

        $this->updateEmployeeDepartmentToTop($corpId, $deleteDepartmentIdList);
        $this->workDepartmentService->deleteWorkDepartments($deleteDepartmentIdList);
    }

    /**
     * 临时将被删除员工的部门转移公司名下.
     */
    private function updateEmployeeDepartmentToTop(int $corpId, array $deleteDepartmentIdList)
    {
        $topDepartment = $this->workDepartmentService->getTopWorkDepartmentByCorpId($corpId, ['id']);
        if (! empty($topDepartment)) {
            $this->workEmployeeDepartmentService->updateWorkEmployeeDepartmentByDepartmentIds($deleteDepartmentIdList, [
                'department_id' => $topDepartment['id'],
            ]);
            $this->workEmployeeService->updateWorkEmployeeByDepartmentIds($deleteDepartmentIdList, [
                'main_department_id' => $topDepartment['id'],
                'wx_main_department_id' => 1,
            ]);
        }
    }

    /**
     * 同步部门详情.
     */
    private function syncDepartmentDetail(int $corpId, array $departmentList)
    {
        if (empty($departmentList)) {
            return;
        }

        $departmentCount = count($departmentList);
        $lastDepartment = 0;
        foreach ($departmentList as $key => $department) {
            if ($departmentCount - 1 === $key) {
                $lastDepartment = 1;
            }
            $this->syncDepartmentQueue->syncDepartmentDetail([
                'corpId' => $corpId,
                'wxDepartmentId' => $department['id'],
                'lastDepartment' => $lastDepartment,
            ]);
        }
    }
}
